//
//  IEnablerService.m
//  UCiEnabler
//
//  Created by Delio Brignoli on 1/08/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "IEnablerService.h"

@implementation IEnablerService

static IEnablerService *sharedIEnablerService = nil;

@synthesize status;
@synthesize operationQueue;
@synthesize currentOperation;

- (id)init {
	self = [super init];
	if (self != nil) {
		self.status = IEnablerServiceStatusUnknown;
		self.currentOperation = nil;
		self.operationQueue = [[NSOperationQueue alloc] init];
		[self.operationQueue setMaxConcurrentOperationCount:1];
	}
	return self;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
	if ([keyPath compare:@"isFinished"] == 0) {
		self.status = self.currentOperation.currentStatus;
	}
}

- (void)startDeducingAccessState {
	if (self.currentOperation != nil) {
		[self.currentOperation removeObserver:self forKeyPath:@"isFinished"];
	}

	if ([[self.operationQueue operations] count] > 0) {
		[self.operationQueue cancelAllOperations];
		[self.operationQueue waitUntilAllOperationsAreFinished];
	}

	self.currentOperation = [[[DeduceAccessOperation alloc] init] autorelease];
	[self.currentOperation addObserver:self forKeyPath:@"isFinished"
	 options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
	 context:NULL];
	
	self.status = IEnablerServiceUpdating;
	[operationQueue addOperation:self.currentOperation];	
}

- (void)startUpdatingAccessTo:(IEnablerStatus)targetStatus forUser:(NSString *)username withPassword:(NSString *)password {
	if (self.currentOperation != nil) {
		[self.currentOperation removeObserver:self forKeyPath:@"isFinished"];
	}

	if ([[self.operationQueue operations] count] > 0) {
		[self.operationQueue cancelAllOperations];
		[self.operationQueue waitUntilAllOperationsAreFinished];
	}

	self.currentOperation = [[[UpdateAccessOperation alloc] initWithStatus:targetStatus for:username with:password] autorelease];
	[self.currentOperation addObserver:self forKeyPath:@"isFinished"
	 options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
	 context:NULL];

	self.status = IEnablerServiceUpdating;
	[operationQueue addOperation:self.currentOperation];
}

- (IEnablerStatus)updateAccessTo:(IEnablerStatus)targetStatus forUser:(NSString *)username withPassword:(NSString *)password {
	self.status = IEnablerServiceUpdating;
	UpdateAccessOperation *op = [[UpdateAccessOperation alloc] initWithStatus:targetStatus for:username with:password];
	[operationQueue addOperation:op];
	[operationQueue waitUntilAllOperationsAreFinished];
	self.status = op.currentStatus;
	[op release];
	return self.status;
}

- (BOOL)errorOccurred {
	return (self.status > 0 && self.status <= _IEnablerServiceLastError);
}

- (NSString *)errorReason {
	return self.currentOperation.reason;
}

- (NSString *)workaroundHint {
	return self.currentOperation.hint;
}


/* Standard singleton boilerplate follows ************************************/

+ (IEnablerService*)sharedIEnablerService
{
    @synchronized(self) {
        if (sharedIEnablerService == nil) {
            [[self alloc] init]; // assignment not done here
        }
    }
    return sharedIEnablerService;
}

+ (id)allocWithZone:(NSZone *)zone
{
    @synchronized(self) {
        if (sharedIEnablerService == nil) {
            sharedIEnablerService = [super allocWithZone:zone];
            return sharedIEnablerService;  // assignment and return on first allocation
        }
    }
    return nil; //on subsequent allocation attempts return nil
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

- (id)retain
{
    return self;
}

- (unsigned)retainCount
{
    return UINT_MAX;  //denotes an object that cannot be released
}

- (void)release
{
    //do nothing
}

- (id)autorelease
{
    return self;
}

@end

